﻿/*
 *  Author: Louis A. Leskoviansky
 *  Company: Artemis Solutions Group (http://www.artemis-solutions.com)
 */


using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using System.Web.UI;


[assembly: WebResource("AjaxControlFramework.CreateTemplate.debug.js", "application/x-javascript")]
[assembly: WebResource("AjaxControlFramework.CreateTemplate.release.js", "application/x-javascript")]

[assembly: WebResource("AjaxControlFramework.ControlTemplate.debug.js", "application/x-javascript")]
[assembly: WebResource("AjaxControlFramework.ControlTemplate.release.js", "application/x-javascript")]

[assembly: WebResource("AjaxControlFramework.NamedMethodTemplate.debug.js", "application/x-javascript")]
[assembly: WebResource("AjaxControlFramework.NamedMethodTemplate.release.js", "application/x-javascript")]


namespace AjaxControlFramework
{
	public class ControlScriptStrategy : ScriptStrategy
	{	
		//------// Properties \\--------------------------------------------\\
		public virtual string CreateTemplateName
		{
			get
			{
				if (base.BuildMode == ScriptBuildMode.Debug)
				{
                    return "AjaxControlFramework.CreateTemplate.debug.js";
				}
				else
				{
                    return "AjaxControlFramework.CreateTemplate.release.js";
				}
			}
		}


		public virtual string ControlTemplateName
		{
			get
			{
				if (base.BuildMode == ScriptBuildMode.Debug)
				{
                    return "AjaxControlFramework.ControlTemplate.debug.js";
				}
				else
				{
                    return "AjaxControlFramework.ControlTemplate.release.js";
				}
			}
		}


		public virtual string NamedMethodTemplateName
		{
			get
			{
				if (base.BuildMode == ScriptBuildMode.Debug)
				{
                    return "AjaxControlFramework.NamedMethodTemplate.debug.js";
				}
				else
				{
                    return "AjaxControlFramework.NamedMethodTemplate.release.js";
				}
			}
		}


		private string _fullTypeName = null;
		public virtual string FullTypeName
		{
			get
			{
				if (_fullTypeName == null)
				{
                    if (TargetControl is TemplateControl)
                    {
                        _fullTypeName = TargetControl.GetType().BaseType.FullName;
                    }
                    else
                    {
                        _fullTypeName = TargetControl.GetType().FullName;
                    }
				}

				return _fullTypeName;
			}
		}
		//------\\ Properties //--------------------------------------------//



		//------// Constructors \\------------------------------------------\\
		public ControlScriptStrategy(Control targetControl)
			: base(targetControl)
		{ }


		public ControlScriptStrategy(Control targetControl, ScriptBuildMode buildMode)
			: base(targetControl, buildMode)
		{ }
		//------\\ Constructors //------------------------------------------//



		//------// Methods \\-----------------------------------------------\\
		public override void GenerateCreateScript(ref TextWriter writer)
		{
			if (writer == null) { throw new ArgumentNullException("writer"); }

			string createScript = base.GetTemplateScriptResource(CreateTemplateName, GetType().BaseType);
            createScript = createScript.Replace("$fulltype$", FullTypeName);
            createScript = createScript.Replace("$escapedfulltype$", FullTypeName.Replace('.', '_'));
            createScript = createScript.Replace("$uniqueid$", TargetControl.UniqueID);
            createScript = createScript.Replace("$autosavecontrolstate$", (!Control.CallbackStrategy.AutoSaveControlState.HasValue || Control.CallbackStrategy.AutoSaveControlState.Value ? "true" : "false"));
            createScript = createScript.Replace("$ajaxstate$", (Control.AjaxContext.State == null ? "{}" : Control.CallbackStrategy.Serializer.SerializeCallbackResult(Control.AjaxContext.State)));

            writer.Write(createScript);
		}


		public override void GenerateControlScript(ref TextWriter writer)
		{
			if (writer == null) { throw new ArgumentNullException("writer"); }

            string controlScript = base.GetTemplateScriptResource(ControlTemplateName, GetType().BaseType);
			controlScript = controlScript.Replace("$fulltype$", FullTypeName);
            controlScript = controlScript.Replace("$parenttype$", "AjaxControlFramework.AjaxControl");

			writer.Write(controlScript);
			GenerateNamedMethodsScript(ref writer);
		}


		public override void GenerateNamedMethodsScript(ref TextWriter writer)
		{
			if (writer == null) { throw new ArgumentNullException("writer"); }

            string namedMethodScript = base.GetTemplateScriptResource(NamedMethodTemplateName, GetType().BaseType);

			MethodInfo[] methods = TargetControl.GetType().BaseType.GetMethods(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance);
			foreach (MethodInfo methodInfo in methods)
			{
				object[] customAttributes = methodInfo.GetCustomAttributes(typeof(AjaxControlMethodAttribute), true);
				if ((customAttributes != null) && (customAttributes.Length > 0))
				{
                    AjaxControlMethodAttribute methodAttribute = (AjaxControlMethodAttribute)customAttributes[0];

					string methodScript = namedMethodScript;
					methodScript = methodScript.Replace("$fulltype$", FullTypeName);
					methodScript = methodScript.Replace("$methodname$", methodInfo.Name);

					StringBuilder parametersBuilder = new StringBuilder();
					ParameterInfo[] parameters = methodInfo.GetParameters();

					if (parameters.Length > 0)
					{
						for (int index = 0; index < parameters.Length - 1; index++)
						{
							parametersBuilder.Append(parameters[index].Name).Append(", ");
						}

						parametersBuilder.Append(parameters[parameters.Length - 1].Name);

						methodScript = methodScript.Replace("$parametersarray$", parametersBuilder.ToString());
						methodScript = methodScript.Replace("$parameters$", parametersBuilder.ToString() + ", ");
					}
					else
					{
						methodScript = methodScript.Replace("$parametersarray$", String.Empty);
						methodScript = methodScript.Replace("$parameters$", String.Empty);
					}


                    if (base.Control.CallbackStrategy != null)
                    {
                        bool handleControlState = true;

                        if (!methodAttribute.EnableControlState.HasValue && !Control.CallbackStrategy.AutoSaveControlState.HasValue)
                        {
                            handleControlState = true;
                        }
                        else if (methodAttribute.EnableControlState.HasValue && !Control.CallbackStrategy.AutoSaveControlState.HasValue)
                        {
                            handleControlState = methodAttribute.EnableControlState.Value;
                        }
                        else if (!methodAttribute.EnableControlState.HasValue && Control.CallbackStrategy.AutoSaveControlState.HasValue)
                        {
                            handleControlState = Control.CallbackStrategy.AutoSaveControlState.Value;
                        }
                        else
                        {
                            handleControlState = (methodAttribute.EnableControlState.Value != Control.CallbackStrategy.AutoSaveControlState.Value ? methodAttribute.EnableControlState.Value : Control.CallbackStrategy.AutoSaveControlState.Value);
                        }

                        methodScript = methodScript.Replace("$handlecontrolstate$", (handleControlState ? "true" : "false"));
                    }
                    else
                    {
                        methodScript = methodScript.Replace("$handlecontrolstate$", "false");
                    }


					writer.Write(methodScript);
				}
			}
		}
		//------\\ Methods //-----------------------------------------------//
	}
}
